/**
 * 工具函数库
 * 提供常用的辅助方法和工具函数
 */

/**
 * 日期时间工具
 */
export const dateUtils = {
  /**
   * 格式化日期
   * @param {Date|String|Number} date 日期
   * @param {String} format 格式 YYYY-MM-DD HH:mm:ss
   * @returns {String} 格式化后的日期字符串
   */
  format(date, format = 'YYYY-MM-DD HH:mm:ss') {
    const d = new Date(date)
    if (isNaN(d.getTime())) return ''
    
    const year = d.getFullYear()
    const month = String(d.getMonth() + 1).padStart(2, '0')
    const day = String(d.getDate()).padStart(2, '0')
    const hours = String(d.getHours()).padStart(2, '0')
    const minutes = String(d.getMinutes()).padStart(2, '0')
    const seconds = String(d.getSeconds()).padStart(2, '0')
    
    return format
      .replace('YYYY', year)
      .replace('MM', month)
      .replace('DD', day)
      .replace('HH', hours)
      .replace('mm', minutes)
      .replace('ss', seconds)
  },
  
  /**
   * 获取相对时间描述
   * @param {Date|String|Number} date 日期
   * @returns {String} 相对时间描述
   */
  getRelativeTime(date) {
    const now = new Date()
    const target = new Date(date)
    const diff = now.getTime() - target.getTime()
    
    const minute = 60 * 1000
    const hour = 60 * minute
    const day = 24 * hour
    const week = 7 * day
    const month = 30 * day
    const year = 365 * day
    
    if (diff < minute) {
      return '刚刚'
    } else if (diff < hour) {
      return `${Math.floor(diff / minute)}分钟前`
    } else if (diff < day) {
      return `${Math.floor(diff / hour)}小时前`
    } else if (diff < week) {
      return `${Math.floor(diff / day)}天前`
    } else if (diff < month) {
      return `${Math.floor(diff / week)}周前`
    } else if (diff < year) {
      return `${Math.floor(diff / month)}个月前`
    } else {
      return `${Math.floor(diff / year)}年前`
    }
  },
  
  /**
   * 获取今日开始时间
   * @returns {Date} 今日开始时间
   */
  getTodayStart() {
    const today = new Date()
    today.setHours(0, 0, 0, 0)
    return today
  },
  
  /**
   * 获取今日结束时间
   * @returns {Date} 今日结束时间
   */
  getTodayEnd() {
    const today = new Date()
    today.setHours(23, 59, 59, 999)
    return today
  },
  
  /**
   * 获取本周开始时间
   * @returns {Date} 本周开始时间
   */
  getWeekStart() {
    const today = new Date()
    const day = today.getDay()
    const diff = today.getDate() - day + (day === 0 ? -6 : 1)
    const monday = new Date(today.setDate(diff))
    monday.setHours(0, 0, 0, 0)
    return monday
  },
  
  /**
   * 获取本月开始时间
   * @returns {Date} 本月开始时间
   */
  getMonthStart() {
    const today = new Date()
    return new Date(today.getFullYear(), today.getMonth(), 1)
  },
  
  /**
   * 判断是否为今天
   * @param {Date|String|Number} date 日期
   * @returns {Boolean} 是否为今天
   */
  isToday(date) {
    const today = new Date()
    const target = new Date(date)
    return today.toDateString() === target.toDateString()
  },
  
  /**
   * 判断是否为本周
   * @param {Date|String|Number} date 日期
   * @returns {Boolean} 是否为本周
   */
  isThisWeek(date) {
    const weekStart = this.getWeekStart()
    const target = new Date(date)
    const weekEnd = new Date(weekStart)
    weekEnd.setDate(weekEnd.getDate() + 6)
    weekEnd.setHours(23, 59, 59, 999)
    
    return target >= weekStart && target <= weekEnd
  }
}

/**
 * 数字工具
 */
export const numberUtils = {
  /**
   * 格式化金额
   * @param {Number} amount 金额
   * @param {Number} decimals 小数位数
   * @returns {String} 格式化后的金额
   */
  formatMoney(amount, decimals = 2) {
    if (isNaN(amount)) return '0.00'
    return Number(amount).toFixed(decimals).replace(/\B(?=(\d{3})+(?!\d))/g, ',')
  },
  
  /**
   * 格式化百分比
   * @param {Number} value 数值
   * @param {Number} decimals 小数位数
   * @returns {String} 格式化后的百分比
   */
  formatPercent(value, decimals = 1) {
    if (isNaN(value)) return '0%'
    return `${Number(value).toFixed(decimals)}%`
  },
  
  /**
   * 生成随机数
   * @param {Number} min 最小值
   * @param {Number} max 最大值
   * @returns {Number} 随机数
   */
  random(min = 0, max = 100) {
    return Math.floor(Math.random() * (max - min + 1)) + min
  },
  
  /**
   * 限制数值范围
   * @param {Number} value 数值
   * @param {Number} min 最小值
   * @param {Number} max 最大值
   * @returns {Number} 限制后的数值
   */
  clamp(value, min, max) {
    return Math.min(Math.max(value, min), max)
  }
}

/**
 * 字符串工具
 */
export const stringUtils = {
  /**
   * 生成随机字符串
   * @param {Number} length 长度
   * @returns {String} 随机字符串
   */
  randomString(length = 8) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
    let result = ''
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length))
    }
    return result
  },
  
  /**
   * 截断字符串
   * @param {String} str 字符串
   * @param {Number} length 长度
   * @param {String} suffix 后缀
   * @returns {String} 截断后的字符串
   */
  truncate(str, length = 50, suffix = '...') {
    if (!str || str.length <= length) return str
    return str.substring(0, length) + suffix
  },
  
  /**
   * 首字母大写
   * @param {String} str 字符串
   * @returns {String} 首字母大写的字符串
   */
  capitalize(str) {
    if (!str) return ''
    return str.charAt(0).toUpperCase() + str.slice(1)
  },
  
  /**
   * 驼峰转下划线
   * @param {String} str 字符串
   * @returns {String} 下划线格式的字符串
   */
  camelToSnake(str) {
    return str.replace(/[A-Z]/g, letter => `_${letter.toLowerCase()}`)
  },
  
  /**
   * 下划线转驼峰
   * @param {String} str 字符串
   * @returns {String} 驼峰格式的字符串
   */
  snakeToCamel(str) {
    return str.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase())
  },
  
  /**
   * 移除HTML标签
   * @param {String} str 字符串
   * @returns {String} 移除HTML标签后的字符串
   */
  stripHtml(str) {
    return str.replace(/<[^>]*>/g, '')
  }
}

/**
 * 数组工具
 */
export const arrayUtils = {
  /**
   * 数组去重
   * @param {Array} arr 数组
   * @param {String} key 对象数组的去重键
   * @returns {Array} 去重后的数组
   */
  unique(arr, key) {
    if (!Array.isArray(arr)) return []
    
    if (key) {
      const seen = new Set()
      return arr.filter(item => {
        const value = item[key]
        if (seen.has(value)) {
          return false
        }
        seen.add(value)
        return true
      })
    }
    
    return [...new Set(arr)]
  },
  
  /**
   * 数组分组
   * @param {Array} arr 数组
   * @param {String|Function} key 分组键或函数
   * @returns {Object} 分组后的对象
   */
  groupBy(arr, key) {
    if (!Array.isArray(arr)) return {}
    
    return arr.reduce((groups, item) => {
      const groupKey = typeof key === 'function' ? key(item) : item[key]
      if (!groups[groupKey]) {
        groups[groupKey] = []
      }
      groups[groupKey].push(item)
      return groups
    }, {})
  },
  
  /**
   * 数组排序
   * @param {Array} arr 数组
   * @param {String} key 排序键
   * @param {String} order 排序方向 asc|desc
   * @returns {Array} 排序后的数组
   */
  sortBy(arr, key, order = 'asc') {
    if (!Array.isArray(arr)) return []
    
    return [...arr].sort((a, b) => {
      let aValue = typeof key === 'function' ? key(a) : a[key]
      let bValue = typeof key === 'function' ? key(b) : b[key]
      
      if (typeof aValue === 'string') {
        aValue = aValue.toLowerCase()
        bValue = bValue.toLowerCase()
      }
      
      if (order === 'desc') {
        return aValue < bValue ? 1 : -1
      }
      return aValue > bValue ? 1 : -1
    })
  },
  
  /**
   * 数组分页
   * @param {Array} arr 数组
   * @param {Number} page 页码
   * @param {Number} pageSize 每页大小
   * @returns {Object} 分页结果
   */
  paginate(arr, page = 1, pageSize = 10) {
    if (!Array.isArray(arr)) return { data: [], total: 0, page: 1, pageSize }
    
    const total = arr.length
    const start = (page - 1) * pageSize
    const end = start + pageSize
    const data = arr.slice(start, end)
    
    return {
      data,
      total,
      page,
      pageSize,
      totalPages: Math.ceil(total / pageSize)
    }
  }
}

/**
 * 对象工具
 */
export const objectUtils = {
  /**
   * 深拷贝
   * @param {Any} obj 对象
   * @returns {Any} 深拷贝后的对象
   */
  deepClone(obj) {
    if (obj === null || typeof obj !== 'object') return obj
    if (obj instanceof Date) return new Date(obj.getTime())
    if (obj instanceof Array) return obj.map(item => this.deepClone(item))
    if (typeof obj === 'object') {
      const cloned = {}
      for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
          cloned[key] = this.deepClone(obj[key])
        }
      }
      return cloned
    }
    return obj
  },
  
  /**
   * 对象合并
   * @param {Object} target 目标对象
   * @param {...Object} sources 源对象
   * @returns {Object} 合并后的对象
   */
  merge(target, ...sources) {
    if (!target) target = {}
    
    sources.forEach(source => {
      if (source) {
        Object.keys(source).forEach(key => {
          if (source[key] && typeof source[key] === 'object' && !Array.isArray(source[key])) {
            target[key] = this.merge(target[key] || {}, source[key])
          } else {
            target[key] = source[key]
          }
        })
      }
    })
    
    return target
  },
  
  /**
   * 获取对象属性值
   * @param {Object} obj 对象
   * @param {String} path 属性路径 'a.b.c'
   * @param {Any} defaultValue 默认值
   * @returns {Any} 属性值
   */
  get(obj, path, defaultValue) {
    if (!obj || !path) return defaultValue
    
    const keys = path.split('.')
    let result = obj
    
    for (const key of keys) {
      if (result === null || result === undefined || !result.hasOwnProperty(key)) {
        return defaultValue
      }
      result = result[key]
    }
    
    return result
  },
  
  /**
   * 设置对象属性值
   * @param {Object} obj 对象
   * @param {String} path 属性路径 'a.b.c'
   * @param {Any} value 属性值
   * @returns {Object} 对象
   */
  set(obj, path, value) {
    if (!obj || !path) return obj
    
    const keys = path.split('.')
    let current = obj
    
    for (let i = 0; i < keys.length - 1; i++) {
      const key = keys[i]
      if (!current[key] || typeof current[key] !== 'object') {
        current[key] = {}
      }
      current = current[key]
    }
    
    current[keys[keys.length - 1]] = value
    return obj
  },
  
  /**
   * 移除对象中的空值
   * @param {Object} obj 对象
   * @returns {Object} 移除空值后的对象
   */
  removeEmpty(obj) {
    if (!obj || typeof obj !== 'object') return obj
    
    const result = {}
    Object.keys(obj).forEach(key => {
      const value = obj[key]
      if (value !== null && value !== undefined && value !== '') {
        if (typeof value === 'object' && !Array.isArray(value)) {
          const cleaned = this.removeEmpty(value)
          if (Object.keys(cleaned).length > 0) {
            result[key] = cleaned
          }
        } else {
          result[key] = value
        }
      }
    })
    
    return result
  }
}

/**
 * 存储工具
 */
export const storageUtils = {
  /**
   * 设置存储
   * @param {String} key 键
   * @param {Any} value 值
   * @param {Number} expire 过期时间（毫秒）
   */
  set(key, value, expire) {
    const data = {
      value,
      expire: expire ? Date.now() + expire : null
    }
    uni.setStorageSync(key, JSON.stringify(data))
  },
  
  /**
   * 获取存储
   * @param {String} key 键
   * @param {Any} defaultValue 默认值
   * @returns {Any} 值
   */
  get(key, defaultValue = null) {
    try {
      const data = uni.getStorageSync(key)
      if (!data) return defaultValue
      
      const parsed = JSON.parse(data)
      
      // 检查是否过期
      if (parsed.expire && Date.now() > parsed.expire) {
        uni.removeStorageSync(key)
        return defaultValue
      }
      
      return parsed.value
    } catch (error) {
      console.error('获取存储失败:', error)
      return defaultValue
    }
  },
  
  /**
   * 移除存储
   * @param {String} key 键
   */
  remove(key) {
    uni.removeStorageSync(key)
  },
  
  /**
   * 清空存储
   */
  clear() {
    uni.clearStorageSync()
  }
}

/**
 * 验证工具
 */
export const validateUtils = {
  /**
   * 验证邮箱
   * @param {String} email 邮箱
   * @returns {Boolean} 是否有效
   */
  isEmail(email) {
    const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    return regex.test(email)
  },
  
  /**
   * 验证手机号
   * @param {String} phone 手机号
   * @returns {Boolean} 是否有效
   */
  isPhone(phone) {
    const regex = /^1[3-9]\d{9}$/
    return regex.test(phone)
  },
  
  /**
   * 验证身份证号
   * @param {String} idCard 身份证号
   * @returns {Boolean} 是否有效
   */
  isIdCard(idCard) {
    const regex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
    return regex.test(idCard)
  },
  
  /**
   * 验证URL
   * @param {String} url URL
   * @returns {Boolean} 是否有效
   */
  isUrl(url) {
    const regex = /^https?:\/\/.+/
    return regex.test(url)
  },
  
  /**
   * 验证密码强度
   * @param {String} password 密码
   * @returns {Object} 验证结果
   */
  checkPasswordStrength(password) {
    const result = {
      score: 0,
      level: 'weak',
      suggestions: []
    }
    
    if (!password) {
      result.suggestions.push('密码不能为空')
      return result
    }
    
    if (password.length < 6) {
      result.suggestions.push('密码长度至少6位')
    } else {
      result.score += 1
    }
    
    if (password.length >= 8) {
      result.score += 1
    }
    
    if (/[a-z]/.test(password)) {
      result.score += 1
    } else {
      result.suggestions.push('包含小写字母')
    }
    
    if (/[A-Z]/.test(password)) {
      result.score += 1
    } else {
      result.suggestions.push('包含大写字母')
    }
    
    if (/\d/.test(password)) {
      result.score += 1
    } else {
      result.suggestions.push('包含数字')
    }
    
    if (/[^\w\s]/.test(password)) {
      result.score += 1
    } else {
      result.suggestions.push('包含特殊字符')
    }
    
    if (result.score >= 5) {
      result.level = 'strong'
    } else if (result.score >= 3) {
      result.level = 'medium'
    }
    
    return result
  }
}

/**
 * 防抖函数
 * @param {Function} func 函数
 * @param {Number} delay 延迟时间
 * @returns {Function} 防抖后的函数
 */
export function debounce(func, delay = 300) {
  let timeoutId
  return function (...args) {
    clearTimeout(timeoutId)
    timeoutId = setTimeout(() => func.apply(this, args), delay)
  }
}

/**
 * 节流函数
 * @param {Function} func 函数
 * @param {Number} delay 延迟时间
 * @returns {Function} 节流后的函数
 */
export function throttle(func, delay = 300) {
  let lastTime = 0
  return function (...args) {
    const now = Date.now()
    if (now - lastTime >= delay) {
      lastTime = now
      func.apply(this, args)
    }
  }
}

/**
 * 导出所有工具
 */
export default {
  dateUtils,
  numberUtils,
  stringUtils,
  arrayUtils,
  objectUtils,
  storageUtils,
  validateUtils,
  debounce,
  throttle
}